package cn.sys.util;

import cn.hutool.json.JSONUtil;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;

/**
 * 文件上传
 * 如果同时有图片文件和普通参数，先调用upload获取文件，这样才能先得到parameterMap中的值，
 * 否则调用getStringInfo获取普通参数时出现空指针异常。
 * getStringInfo中如果再将parameterMap赋以便值，得到的集合是空的，也报空指针异常错误
 */
public class FileUploadUtil {
    // 1. 构建工厂对象
    private static FileItemFactory factory = new DiskFileItemFactory();
    // 2. 构建文件上传对象
    private static ServletFileUpload servletFileUpload = new ServletFileUpload(factory);
    // 3. 创建map集合得到请求中的数据；创建list集合存放图片文件名
    private static Map<String, List<FileItem>> parameterMap = null;

    /**
     * 文件上传操作
     * 将获取到的文件名数组转为JSON数组返回，如果需要存入数据库就取用；不存入数据库就不用
     * @param req   requset请求对象
     * @param key   前端传入的文件key值
     * @param filePath  文件写入的新位置
     * @return  获取到的文件名组成的JSON数组
     */
    public static String upload(HttpServletRequest req, String key, String filePath){
        List<String> fileUrls = new ArrayList<>();
        try {
            // 4. 得到请求数据中的FileItem集合
            parameterMap = servletFileUpload.parseParameterMap(req);
            List<FileItem> fileItems = parameterMap.get(key);
            // 5. 遍历得到数据
            for(FileItem fileItem: fileItems){
                //System.out.println(image.getName());
                // 5.1 获取原始文件名
                String oldFileName = fileItem.getName();
                // 5.2 获取后缀名
                String suffixName = fileItem.getName().substring(oldFileName.lastIndexOf("."));
                // 5.3 生成随机新文件名，并拼上后缀名（避免文件名重复造成的覆盖）
                String newFileName = UUID.randomUUID().toString() + suffixName;
                // 5.4 添加到文件名list集合中，存好后转为JSON数组格式，为存入数据库做准备
                fileUrls.add(newFileName);
                // 5.5 写入到新的指定文件夹中
                File file = new File(filePath);
                if(!file.exists()){
                    file.mkdir();
                }
                fileItem.write(new File(filePath + File.separator + newFileName));
            }
        } catch (FileUploadException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        String jsonFileUrls = JSONUtil.toJsonStr(fileUrls);
        return jsonFileUrls;
    }

    /**
     * 前端传过来的非文件信息的解析
     * @param req   requset请求对象
     * @param key   前端传入的非文件的key值
     * @return
     */
    public static String getStringInfo(HttpServletRequest req, String key) {
        try {
            if(parameterMap == null) {
                parameterMap = servletFileUpload.parseParameterMap(req);
            }
        } catch (FileUploadException e) {
            e.printStackTrace();
        }   //  如果已经给parameterMap赋值过一次，就不能再用servletFileUpload对其赋值了，为什么？？？
        List<FileItem> fileItem = parameterMap.get(key);
        String info = "";
        try {
             info = new String(fileItem.get(0).get(), "utf-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return info.trim();
    }

    /**
     * 前端传入表格文件，解析文件获取其中的内容，用作对学生数据的批量插入
     * @param req
     * @param key
     * @return
     */
    public static List<Map<String, Object>> getMapInfoFromExcel(HttpServletRequest req, String key) throws IOException {
        List<Map<String, Object>> excelInfo = new ArrayList<>();
        try {
            parameterMap = servletFileUpload.parseParameterMap(req);
            List<FileItem> fileItems = parameterMap.get(key);
            FileItem excelItem =  fileItems.get(0);     // excel文件只能读一个
            // 获取输入流对象，对文件进行解析
            InputStream is = excelItem.getInputStream();
            ExcelReader excelReader = ExcelUtil.getReader(is);
            excelInfo = excelReader.readAll();
        } catch (FileUploadException e) {
            e.printStackTrace();
        }
        return excelInfo;
    }
}
